from minio import Minio, S3Error
from fastapi import FastAPI, HTTPException
from dataclasses import dataclass
from jinja2 import Template, FileSystemLoader, Environment
import custom_config

j2_loader = FileSystemLoader('./j2_files')
env = Environment(loader=j2_loader)

# 数据读取接口
class DataSource:
    def create_data_source_object(self):
        # 创建声明数据源对象的字符串
        return ""

# 数据源 Minio
@dataclass
class MinioDataSource(DataSource):
    url: str = custom_config.MINIO_API_URL
    access_key: str = custom_config.MINIO_ACCESS_KEY
    secret_key: str = custom_config.MINIO_SECRET_KEY
    secure: bool = False
    bucket_name: str = ""
    object_name: str = ""

    def __init__(self):
        pass

    def create_data_source_object(self):
        j2_tmpl = env.get_template('./read_file_from_minio.j2')
        result = j2_tmpl.render(
            url=self.url,
            access_key=self.access_key,
            secret_key=self.secret_key,
            secure=self.secure,
            bucket_name=self.bucket_name,
            object_name=self.object_name
        )
        return result

# 装饰器抽象类
class DataConvertDecorator(DataSource):
    def __init__(self, data_source, dataframe_name):
        self._data_source = data_source
        self._dataframe_name = dataframe_name

    def create_data_source_object(self):
        # 增加对数据源的转换操作
        return self._data_source.create_data_source_object()

# 装饰器 csv 转换 pandas dataframe
class ConvertCsvToDataframeDecorator(DataConvertDecorator):
    def create_data_source_object(self):
        j2_tmpl = env.get_template('./pandas_read.j2')
        read_str = j2_tmpl.render(read_function="read_csv", df_name=self._dataframe_name)
        datasource_str = super().create_data_source_object()
        return datasource_str + "\n" + read_str

def readfile_from_minio(item: MinioDataSource):
    if item is not None:
        minio_client = Minio(
            item.url,  # MinIO服务器地址
            access_key=item.access_key,
            secret_key=item.secret_key,
            secure=item.secure
        )
        # 检查bucket是否存在
        if not minio_client.bucket_exists(item.bucket_name):
            raise HTTPException(status_code=404, detail="bucket doesn't exist")
        try:
            data = minio_client.get_object(item.bucket_name, item.object_name)
            return data
        except S3Error as exc:
            raise HTTPException(status_code=404, detail="object doesn't exist or open failed")
    else:
        raise HTTPException(status_code=404, detail="item is null or empty")